Comparison of all 14 MI House Representative disbursements to representative staffers from FEC funds.
Nature of the Review¶
Rep. Huizenga's campaign committee, Huizenga for Congress ("Campaign Committee"), may have accepted contributions from individuals employed in Rep. Huizenga's congressional office. If Rep. Huizenga failed to ensure that his campaign committee complied with applicable rules, regarding contributions from congressional employees, then he may have violated House rules, standards of conduct, and federal law.
The Campaign Committee reported campaign disbursements that may not be legitimate and verifiable campaign expenditures attributable to bona fide campaign or political purposes. If Rep. Huizenga converted campaign funds from the Campaign Committee to personal use, or if Rep. Huizenga's Campaign Committee expended funds that were not attributable to bona fide campaign or political purposes, then Rep. Huizenga may have violated House rules, standards of conduct, and fedteral law.OCE Recommendation¶
The Board recommended that the Committee further review the above allegation concerning Rep. Huizenga because there is substantial reason to believe that Rep. Huizenga's Campaign Committee accepted contributions from individuals employed in Rep. Huizenga's congressional office.
The Board recommended that the Committee further review the above allegation concerning Rep. Huizenga because tehre[sic] is substantial rea son to believe that Rep. Huizenga's Campaign Committee reported campaign disbursements that were not legitimate and verifiable campaign expenditures attributable to bona fide campaign or political purposes.
Source: OCE Referral Regarding Rep. Bill Huizenga, Nov 14, 2019
%matplotlib inline
from __init import *
from lookup import Congressman
Generate pretty plots for printing.
# https://stackoverflow.com/questions/332289/how-do-you-change-the-size-of-figures-drawn-with-matplotlib#comment87590438_41717533
sns.set(
rc={
"axes.labelsize": 12,
"axes.titlesize": 18,
"figure.figsize": (11, 8.5),
"figure.dpi": 300,
"figure.facecolor": "w",
"figure.edgecolor": "k",
}
)
Read all of the Michigan disbursement data & reps data.
df = pd.read_csv(
filepath_or_buffer="mi_rep_all_disbursement_data.csv.gz",
compression="gzip",
header=0,
)
# Load all representative data.
reps = lookup.savepoint()
# Get MI Reps.
mi = [rep for rep in reps if rep.state_abbr == "MI"]
mi_reps = [rep for rep in mi if rep.house]
mi_senate = [rep for rep in mi if rep.senate]
Look through each Michigan rep and their staffers and find disbursements.
df2=pd.DataFrame()
for rep in mi_reps:
for staffer in rep.staffers2.keys():
staffer_name = HumanName(staffer)
df_ = df[
df.recipient_name.str.contains(",") &
df.recipient_name.str.contains(staffer_name.first.upper()) &
df.recipient_name.str.contains(staffer_name.last.upper()) &
df.committee_name.str.contains(rep.last_name.upper())
]
# If the staffer recieved any disbursements.
if len(df_)>0:
# Get the total and round to cents. Otherwise floating point numbers do weird things.
total = np.round(df_.disbursement_amount.sum(), 2)
print(f"{rep.state_abbr}-{rep.district}\t{rep.name}: {staffer_name}, {len(df_)} disbursements: ${total}")
df2 = df2.append(
other=df_,
verify_integrity=True,
)
df2.reset_index(inplace=True)
Count and Sum total of disbursements to representative staffers. Sorted by disbursement sum.
_ = df2.groupby("committee_name").agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_.sort_values(by=[("disbursement_sum")], inplace=True)
_
ax = _["disbursement_sum"].plot(kind='bar')
# Labels
plt.xlabel("Committee Name")
plt.ylabel("Total Value of Disbursements")
ax.yaxis.set_major_formatter(dollar_tick)
# Title & Save
fig_no=1
title = f"Fig {fig_no}. MI Representative Staff Campaign Disbursements"
plt.title(title)
plt.savefig(f"{title}.png", transparent=False, bbox_inches='tight')
_ = df2.groupby(['committee_name','recipient_name']).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_
Before further analysis, normalize the recipient names.
For what ever reason, Huizenga has the most 'variety' in recipient names. Making it annoying to aggregate results.
For example:
DEWITTE, JON 18653.56
DEWITTE, JON MR. 44530.23
"Mr." splits Jon's disbursements into two. Hanlon's razor?
def norm_name(recipient_name):
# Normalize dashes added to Brian Patrick & Matt Kooiman's names.
recipient_name = recipient_name.replace("-", "")
# Normalize MCMANUS, MARLISS's married name.
recipient_name = recipient_name.replace("BROWDER ", "")
# Use HumanName to strip out titles.
hn = HumanName(recipient_name)
return f'{hn["last"]}, {hn["first"]}'
df2["recipient"] = df2.recipient_name.apply(norm_name)
_ = df2.groupby(["committee_name", "recipient"]).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_
_.sort_values(by=[("disbursement_count")])
_.sort_values(by=[("disbursement_sum")])
_ = df2.groupby(['committee_name','disbursement_description']).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_
As shown in Fig 1., Huizenga's staff disbursements is inline (but still higher) with disbursements taken by other Michigan representative staffers. However all other campaigns have considerable spending for salary/payroll.
For the purposes of this analysis "Salary" & "Payroll" are synonymous.
# Determine if a disbursement
def ispayroll(disbursement_description):
if "SALARY" in disbursement_description:
return "Payroll"
# Edgecase for a typo.
if "PAYROL" in disbursement_description:
return "Payroll"
return "Non-Payroll"
# Force disbursement_description to a string.
df2["disbursement_description"] = df2.disbursement_description.apply(str)
# Add payroll column.
df2["payroll"] = df2.disbursement_description.apply(ispayroll)
_ = df2.groupby(['committee_name', "payroll"]).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_
ax = _["disbursement_sum"].unstack().plot(kind='bar', stacked=True)
# Labels
plt.xlabel("Committee Name")
plt.ylabel("Total Amount of Disbursements")
ax.yaxis.set_major_formatter(dollar_tick)
plt.legend(bbox_to_anchor=(1, 1))
# Title & Save
fig_no+=1
title = f"Fig {fig_no}. Payroll vs Non-Payroll Campaign Staff Disbursements"
plt.title(title)
plt.savefig(f"{title}.png", transparent=False, bbox_inches='tight')
_ = df2.groupby(["payroll", 'committee_name']).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_.sort_values(by=["payroll", "disbursement_sum"], inplace=True)
_
ax = _["disbursement_sum"].unstack().plot(kind='bar', stacked=True)
# Labels
plt.xlabel("")
plt.ylabel("Total Value of Disbursements")
ax.yaxis.set_major_formatter(dollar_tick)
# Title & Save
fig_no+=1
title = f"Fig {fig_no}. Campaign Staff Disbursements, Payroll vs Non-Payroll"
plt.title(title)
plt.legend(title="Committee Name", loc='bottom left', bbox_to_anchor=(1.0, 1))
plt.savefig(f"{title}.png", transparent=False, bbox_inches='tight')
Looking into just disbursements made to legislative staff that were not for payroll purposes.
Review No. 19-2187:
II: REP. HUIZENGA’S CAMPAIGN COMMITTEE MAY HAVE ACCEPTED CONTRIBUTIONS FROM CONGRESSIONAL STAFFERS
A. Applicable Law, Rules, and Standards of Conduct
- House Ethics Manual
“The definition of the term contribution in the FECA is quite detailed . . . [U]nder FEC regulations, most outlays that an individual makes on behalf of a campaign are deemed to be a contribution to that campaign from that individual. This is so even if it is intended that the campaign will reimburse the individual promptly. The major exception to this rule is for outlays that an individual makes to cover expenses that he or she incurs in traveling on behalf of a campaign.” 10 Assuming certain travel outlays are reimbursed within specified time periods, they will not be considered “contributions.”
Sorted by disbursement total.
non_payroll_df = df2[df2.payroll == "Non-Payroll"]
_ = non_payroll_df.groupby(['committee_name']).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_.sort_values(by="disbursement_sum", inplace=True)
_
ax = _["disbursement_sum"].plot(kind="bar")
# Labels
plt.xlabel("Committee Name")
plt.ylabel("Total Value of Disbursements")
ax.yaxis.set_major_formatter(dollar_tick)
# Title & Save
fig_no+=1
title = f"Fig {fig_no}. Non-Payroll Staff Disbursements"
plt.title(title)
plt.savefig(f"{title}.png", transparent=False, bbox_inches='tight')
Sorted by total disbursement sum.
_ = non_payroll_df.groupby(['recipient', 'committee_name']).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_.sort_values(by="disbursement_sum", inplace=True)
_
ax = _["disbursement_sum"].unstack().plot(kind="bar", stacked=True)
# Labels
plt.xlabel("Disbursement Recipient")
plt.ylabel("Total Value of Disbursements")
ax.yaxis.set_major_formatter(dollar_tick)
plt.legend(title="Committee Name", bbox_to_anchor=(1.0, 1))
# Title & Save
fig_no+=1
title = f"Fig {fig_no}. Non-Payroll Staff Disbursements, by Recipient"
plt.title(title)
plt.savefig(f"{title}.png", transparent=False, bbox_inches='tight')
_ = non_payroll_df.groupby(['committee_name', 'disbursement_purpose_category']).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_
ax = _["disbursement_sum"].unstack().plot(kind='bar', stacked=True)
# Labels
plt.xlabel("Committee Name")
plt.ylabel("Total Value of Disbursements")
ax.yaxis.set_major_formatter(dollar_tick)
# Title & Save
fig_no+=1
title = f"Fig {fig_no}. Non-Payroll Staff Disbursement, Grouped By Committee Name & Disbursement Category"
plt.title(title)
plt.savefig(f"{title}.png", transparent=False, bbox_inches='tight')
“The definition of the term contribution in the FECA is quite detailed . . . [U]nder FEC regulations, most outlays that an individual makes on behalf of a campaign are deemed to be a contribution to that campaign from that individual. This is so even if it is intended that the campaign will reimburse the individual promptly. The major exception to this rule is for outlays that an individual makes to cover expenses that he or she incurs in traveling on behalf of a campaign.” Assuming certain travel outlays are reimbursed within specified time periods, they will not be considered “contributions.”
material_df = non_payroll_df[non_payroll_df.disbursement_purpose_category=="MATERIALS"]
_ = material_df.groupby(['committee_name','disbursement_description']).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_
ax = _["disbursement_sum"].unstack().plot(kind='bar', stacked=True)
# Labels
plt.xlabel("Committee Name")
plt.ylabel("Total Value of Disbursements")
ax.yaxis.set_major_formatter(dollar_tick)
# Title & Save
fig_no+=1
title = f"Fig {fig_no}. Non-Payroll Staff Material Disbursement"
plt.title(title)
plt.savefig(f"{title}.png", transparent=False, bbox_inches='tight')
_ = material_df.groupby(['committee_name','recipient', 'disbursement_description']).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_
What campaign staff gets reimbursed most for driving.
df.disbursement_description = df.disbursement_description.apply(str)
mileage_df = df2[
df2.disbursement_description.str.contains("MILE")
]
_ = mileage_df.groupby(['committee_name']).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_.sort_values(by="disbursement_sum", inplace=True)
_
ax = _["disbursement_sum"].plot(kind='bar', stacked=True)
# Labels
plt.xlabel("Committee Name")
plt.ylabel("Total Value of Disbursements")
ax.yaxis.set_major_formatter(dollar_tick)
# Title & Save
fig_no+=1
title = f"Fig {fig_no}. Staff Mileage Disbursement"
plt.title(title)
plt.savefig(f"{title}.png", transparent=False, bbox_inches='tight')
_ = mileage_df.groupby(['committee_name','disbursement_description']).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_
Sorted by total disbursement sum.
_ = mileage_df.groupby(['recipient', 'committee_name']).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_.sort_values(by="disbursement_sum", inplace=True)
_
ax = _["disbursement_sum"].unstack().plot(kind='bar', stacked=True)
# Labels
plt.xlabel("Recipient")
plt.ylabel("Total Value of Disbursements")
ax.yaxis.set_major_formatter(dollar_tick)
# Title & Save
fig_no+=1
title = f"Fig {fig_no}. Staff Mileage Disbursement, By Staffer"
plt.title(title)
plt.savefig(f"{title}.png", transparent=False, bbox_inches='tight')
What campaign staff gets reimbursed most for "Consulting" work.
df.disbursement_description = df.disbursement_description.apply(str)
consulting_df = df2[
df2.disbursement_description.str.contains("CONSULT")
]
_ = consulting_df.groupby(['committee_name']).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_.sort_values(by="disbursement_sum", inplace=True)
_
ax = _["disbursement_sum"].plot(kind='bar', stacked=True)
# Labels
plt.xlabel("Committee Name")
plt.ylabel("Total Value of Disbursements")
ax.yaxis.set_major_formatter(dollar_tick)
# Title & Save
fig_no+=1
title = f"Fig {fig_no}. Staff Consulting Disbursement"
plt.title(title)
plt.savefig(f"{title}.png", transparent=False, bbox_inches='tight')
_ = consulting_df.groupby(['committee_name','disbursement_description']).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_
Sorted by total disbursement sum.
_ = mileage_df.groupby(['recipient', 'committee_name']).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_.sort_values(by="disbursement_sum", inplace=True)
_
ax = _["disbursement_sum"].unstack().plot(kind='bar', stacked=True)
# Labels
plt.xlabel("Recipient")
plt.ylabel("Total Value of Disbursements")
ax.yaxis.set_major_formatter(dollar_tick)
# Title & Save
fig_no+=1
title = f"Fig {fig_no}. Staff Consulting Disbursements, Grouped by Recipient"
plt.title(title)
plt.savefig(f"{title}.png", transparent=False, bbox_inches='tight')
What campaign staff gets reimbursed most for "Other" & what disbursement purposes does each compaign count as 'Other'.
df.disbursement_description = df.disbursement_description.apply(str)
non_payroll_other_df = non_payroll_df[
non_payroll_df.disbursement_purpose_category == "OTHER"
]
Sorted by total disbursement sum.
_ = non_payroll_other_df.groupby(['committee_name']).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_.sort_values(by="disbursement_sum", inplace=True)
_
ax = _["disbursement_sum"].plot(kind='bar', stacked=True)
# Labels
plt.xlabel("Committee Name")
plt.ylabel("Total Value of Disbursements")
ax.yaxis.set_major_formatter(dollar_tick)
# Title & Save
fig_no+=1
title = f"Fig {fig_no}. Non-Payroll 'Other' Disbursements"
plt.title(title)
plt.savefig(f"{title}.png", transparent=False, bbox_inches='tight')
_ = non_payroll_other_df.groupby(['committee_name','disbursement_description']).agg({"disbursement_amount": ["count", "sum"]})
_.columns = ["_".join(x) for x in _.columns.ravel()]
_.columns=[c.replace("_amount", "") for c in _.columns]
_